package wcg;

import ikelib.drawTools;
import ikelib.wintime;

import javax.swing.JPanel;

import java.awt.Button;
import java.awt.Component;
import java.awt.Frame;
import java.awt.BorderLayout;
import java.awt.Point;

import javax.swing.DefaultCellEditor;
import javax.swing.DefaultListModel;
import javax.swing.JDialog;
import javax.swing.JList;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.ListSelectionModel;

import java.awt.Rectangle;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.MouseEvent;
import java.awt.event.MouseListener;

import javax.swing.JScrollPane;
import javax.swing.JButton;
import javax.swing.event.CellEditorListener;
import javax.swing.event.ChangeEvent;
import javax.swing.event.ListSelectionEvent;
import javax.swing.event.ListSelectionListener;
import javax.swing.table.DefaultTableColumnModel;
import javax.swing.table.DefaultTableModel;
import javax.swing.table.TableCellEditor;
import javax.swing.table.TableCellRenderer;
import javax.swing.table.TableColumn;
import javax.swing.table.TableColumnModel;
import javax.swing.tree.TreeSelectionModel;
import java.awt.Dimension;
import java.awt.GridBagLayout;
import java.awt.GridBagConstraints;
import java.awt.GridLayout;
import java.util.EventObject;

import javax.swing.BoxLayout;
import javax.swing.JTable;

import GraphicView.GraphicView;


import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.FlowLayout;


public class DialogTimeMarker extends JDialog  {

	private static final long serialVersionUID = 1L;
	private JPanel jContentPane = null;
	private JScrollPane jScrollPane = null;
	private JButton jButtonClose = null;
	private JButton jButtonRemove = null;
	//private DefaultListModel ListModel = new DefaultListModel(); //@
	private GraphicView Parent=null; //@
	private JPanel jPanelButton = null;
	private int CurrentAutoIndex=1;
	private JTable jTableMarker = null;//@

	
	private String[] TableColumnName = {"Index","Time","From marker [0]","Go"};
	private Object[][] TableData = {
			//{new Integer(0),new String(""),new String("")}
	};
	private CustomTableModel TableModel=null;//@
	private JButton btnAdd;
	
	private  int AddSpecialMarkerNum = 10; // number of adding marker 
	private  int AddSpecialMarkerStep = 60; // sec;

	//------------------------------------------------------
	//　テーブルモデル
	public class CustomTableModel extends DefaultTableModel {
		private static final long serialVersionUID = 1L;
	    CustomTableModel(Object[][] tableData, String[] tableColumnName) {
			super(tableData,tableColumnName);
		}

		public Class<?> getColumnClass(int col){
			switch(col){
			case 0: return Integer.class;
			case 1: return String.class;
			case 2: return String.class;
			case 3: return Button.class;
			default: return String.class;
			}
	    }

	}
	//------------------------------------------------------
	//　JTableにボタンを表示するために
    public class JumpButton extends JButton {  
        
        @Override  
        public void updateUI() {  
            super.updateUI();  
            setFocusable(false);  
            setText("Go");  
        }  
    }  
    public class JumpButtonRenderer extends JumpButton implements TableCellRenderer {  
        
        public JumpButtonRenderer() {  
            super();  
            setName("Table.cellRenderer");  
        }  
      
        public Component getTableCellRendererComponent(  
                JTable jtable, Object o, boolean bln, boolean bln1, int i, int i1) {  
            return this;  
        }  
    }
     // --------------------------------------------------------------------------
    public class JumpButtonEditor extends JumpButton implements TableCellEditor {  
        
        public JumpButtonEditor(final JTable table) {  
            super();  
            addActionListener(new ActionListener() {  
      
                public void actionPerformed(ActionEvent ae) {  
                    int row = table.convertRowIndexToModel(table.getEditingRow());  
                    fireEditingStopped();  
                    doJump();
                   // ((DefaultTableModel)table.getModel()).removeRow(row);  
                }  
            });  
        }  
          
        public Component getTableCellEditorComponent(  
                JTable jtable, Object o, boolean bln, int i, int i1) {  
            return this;  
        }  
      
        public Object getCellEditorValue() {  
            return "";  
        }  
      
        public boolean isCellEditable(EventObject eo) {  
            return true;  
        }  
      
        public boolean shouldSelectCell(EventObject eo) {  
            return true;  
        }  
      
        public boolean stopCellEditing() {  
            fireEditingStopped();  
            return true;  
        }  
      
        public void cancelCellEditing() {  
            fireEditingCanceled();  
        }  
      
        public void addCellEditorListener(CellEditorListener cl) {  
            listenerList.add(CellEditorListener.class, cl);  
        }  
      
        public void removeCellEditorListener(CellEditorListener cl) {  
            listenerList.remove(CellEditorListener.class, cl);  
        }  
        public CellEditorListener[] getCellEditorListeners() {  
            return (CellEditorListener[])listenerList.getListeners(CellEditorListener.class);  
        }  
        protected void fireEditingStopped() {  
            // Guaranteed to return a non-null array  
            Object[] listeners = listenerList.getListenerList();  
            // Process the listeners last to first, notifying  
            // those that are interested in this event  
            for(int i = listeners.length-2; i>=0; i-=2) {  
                if(listeners[i]==CellEditorListener.class) {  
                    // Lazily create the event:  
                    if(changeEvent == null) changeEvent = new ChangeEvent(this);  
                    ((CellEditorListener)listeners[i+1]).editingStopped(changeEvent);  
                }  
            }  
        }  
        protected void fireEditingCanceled() {  
            // Guaranteed to return a non-null array  
            Object[] listeners = listenerList.getListenerList();  
            // Process the listeners last to first, notifying  
            // those that are interested in this event  
            for(int i = listeners.length-2; i>=0; i-=2) {  
                if(listeners[i]==CellEditorListener.class) {  
                    // Lazily create the event:  
                    if(changeEvent == null) changeEvent = new ChangeEvent(this);  
                    ((CellEditorListener)listeners[i+1]).editingCanceled(changeEvent);  
                }  
            }  
        }  
    }  
    //--------------------------------------
    // 編集終了を知るために
    public class EditEndNotifyListener implements CellEditorListener {
		@Override
		public void editingCanceled(ChangeEvent arg0) {
			setDiff();
			Parent.repaintAll();
		
		}

		@Override
		public void editingStopped(ChangeEvent arg0) {
			setDiff();
			Parent.repaintAll();

		}
    }
    public class  EditEndNotifyEditor extends DefaultCellEditor{
     	public EditEndNotifyEditor(JTextField textField){
    		super(textField);
    		setClickCountToStart( 1 );
    		//リスナー追加
    		addCellEditorListener( new EditEndNotifyListener() );
    	}
    	
    }
 
    
	public void setParent(GraphicView p){
		Parent = p;
	}
	/**
	 * @param owner
	 */
	private Frame Owner = null;
	public DialogTimeMarker(Frame owner) {
		super(owner);
		Owner = owner;
		initialize();
		
	}

	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setSize(500, 293);
		this.setTitle("Time Marker");  // Generated
		this.setContentPane(getJContentPane());
	}

	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private JPanel getJContentPane() {
		if (jContentPane == null) {
			BorderLayout borderLayout = new BorderLayout();
			borderLayout.setHgap(0);
			borderLayout.setVgap(0);
			jContentPane = new JPanel();
			jContentPane.setLayout(borderLayout);
			jContentPane.add(getJPanelButton(), BorderLayout.SOUTH);
			jContentPane.add(getJScrollPane(), BorderLayout.CENTER);
		}
		return jContentPane;
	}

	/**
	 * This method initializes jScrollPane	
	 * 	
	 * @return javax.swing.JScrollPane	
	 */
	private JScrollPane getJScrollPane() {
		if (jScrollPane == null) {
			jScrollPane = new JScrollPane();
			jScrollPane.setViewportView(getJTableMarker());
			jScrollPane.addMouseListener(new java.awt.event.MouseAdapter() {
				public void mouseClicked(java.awt.event.MouseEvent e) {
				}
			});
		}
		return jScrollPane;
	}

	/**
	 * This method initializes jButtonClose	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJButtonClose() {
		if (jButtonClose == null) {
			jButtonClose = new JButton();
			jButtonClose.setText("Close");
			jButtonClose.setPreferredSize(new Dimension(80,25));
			jButtonClose.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					setVisible(false);
				}
			});
		}
		return jButtonClose;
	}

	/**
	 * This method initializes jButtonRemove	
	 * 	
	 * @return javax.swing.JButton	
	 */
	private JButton getJButtonRemove() {
		if (jButtonRemove == null) {
			jButtonRemove = new JButton();
			jButtonRemove.setText("Remove");  // Generated
			jButtonRemove.setPreferredSize(new Dimension(80,25));
			jButtonRemove.addActionListener(new java.awt.event.ActionListener() {
				public void actionPerformed(java.awt.event.ActionEvent e) {
					int max = jTableMarker.getSelectedRowCount();
					int firstrow = jTableMarker.getSelectedRow();
					for(int i=0;i<max;i++){
						int row;
						//if(row >= 0){
							row = jTableMarker.convertRowIndexToModel(firstrow);
							TableModel.removeRow(row);
						//}
					}
					setDiff();
					Parent.repaintAll();
				}
			});
		}
		return jButtonRemove;
	}
	private int findMarkerViewIndex(int idx){
		int[] dat = getMarkerIndex();
		int col = getColumnFromName("Index");
		for(int i=0;i<jTableMarker.getRowCount();i++){
			Object obj = jTableMarker.getValueAt(i,col);
			Integer id = Integer.valueOf(obj.toString());
			if(idx == id) return i;
		}
		return -1;
	}
	
	private int getColumnFromName(String name){
		int i;
		for(i=0;i<TableColumnName.length;i++){
			if(TableColumnName[i].compareToIgnoreCase(name)==0) break;
		}
		return i;
	}
	private wintime getWinTimeFromTable(int row,int col){
		Object obj = jTableMarker.getValueAt(row,col);
		String ts = obj.toString();
		wintime wt = new wintime();
		wt.parseDaySec(ts);
		return wt;
	}
	private void setDiff(){
		int index = findMarkerViewIndex(0);
		int tmidx = getColumnFromName("Time");
		int dfidx = getColumnFromName("From marker [0]");
		if(index>=0){	// リファレンスマーカあり
			wintime wt = getWinTimeFromTable(index,tmidx);
			for(int i=0;i<jTableMarker.getRowCount();i++){
				if(i==index) continue;
				wintime wt2 = getWinTimeFromTable(i,tmidx);
				long diff = wt2.getValueU() - wt.getValueU();
				//String mes=String.format("%9.6f sec", (float)diff/1000000f);
				String mes = drawTools.timeSpanString(diff);
				String freq = drawTools.freqString(diff);
				mes = mes + " (" + freq + ")";
				jTableMarker.setValueAt(mes, i, dfidx);
			}
		}
		else{
			for(int i=0;i<jTableMarker.getRowCount();i++){
				if(i==index) continue;
				jTableMarker.setValueAt("", i, dfidx);
			}
		}
	}
	public void addTime(wintime tm,int idx){
		jTableMarker.clearSelection();
		if(idx<0) idx = CurrentAutoIndex++;
		int index = findMarkerViewIndex(idx);
		if(index>=0){
			index = jTableMarker.convertRowIndexToModel(index);
			TableModel.removeRow(index);
		}
		int row = jTableMarker.getRowCount();
		
		TableModel.insertRow(row,TableData);
		int tblidx = getColumnFromName("Index");
		TableModel.setValueAt(idx,row,tblidx);
		int tmidx = getColumnFromName("Time");
		TableModel.setValueAt(tm.fmtDay()+ " " + tm.fmtuSec(),row,tmidx);
		tmidx = getColumnFromName("Go");
		TableModel.setValueAt(new Button("Go"),row,tmidx);
		setDiff();
		Parent.repaintAll();
		setVisible(true);
	}
	
	private wintime getWinTimeFromText(String str){
		String[] tok = str.split(";");
		str = tok[0];
		str.trim();
		if(str.isEmpty()) return null;
		wintime wt=new wintime();
		wt.parseDaySec(str);
		return wt;
		
	}
	private int getMarkerIndexFromText(String str){
		String[] tok = str.split(";");
		if(tok.length<=1) return 0;
		String s = tok[1].trim();
		int ret=0;
		try{
			ret = Integer.valueOf(s);
		}catch(NumberFormatException e){
			
		}
		return ret;
	}
	private wintime getSelectedWinTime(){
		int row = jTableMarker.getSelectedRow();
		int column = getColumnFromName("Time");
		Object obj = jTableMarker.getValueAt(row, column);
		if(obj==null) return null;
		String str = obj.toString();
		return getWinTimeFromText(str);
	}
	
	public wintime[] getWinTime(){
		int num = jTableMarker.getRowCount();
		wintime[] ret = new wintime[num];
		
		int column = getColumnFromName("Time");
		for(int i=0;i<num;i++){
			Object obj = jTableMarker.getValueAt(i, column);
			String str = obj.toString();
			wintime wt = getWinTimeFromText(str);
			ret[i] = wt;
		}
		return ret;
	}
	public int[] getMarkerIndex(){
		int num = jTableMarker.getRowCount();
		int[] ret = new int[num];
		
		int column = getColumnFromName("Index");
		for(int i=0;i<num;i++){
			Object obj = jTableMarker.getValueAt(i, column);
			String str = obj.toString();
			ret[i] = Integer.valueOf(str);
		}
		return ret;
	}
	private void doJump(){
		wintime wt = getSelectedWinTime();
		if(wt==null) return;
		Parent.setDispTimeCenter(wt);
	}
	/**
	 * This method initializes jPanelButton	
	 * 	
	 * @return javax.swing.JPanel	
	 */
	private JPanel getJPanelButton() {
		if (jPanelButton == null) {
			jPanelButton = new JPanel();
			jPanelButton.setPreferredSize(new Dimension(100, 35));
			jPanelButton.setLayout(new FlowLayout(FlowLayout.CENTER, 5, 5));
			jPanelButton.add(getJButtonRemove());  // Generated
			jPanelButton.add(getBtnAdd());
			jPanelButton.add(getJButtonClose());
		}
		return jPanelButton;
	}
	/**
	 * This method initializes jTableMarker	
	 * 	
	 * @return javax.swing.JTable	
	 */
	private JTable getJTableMarker() {
		if (jTableMarker == null) {
			TableModel = new CustomTableModel(TableData,TableColumnName); 	//@ 
			//TableModel = new CustomTableModel(); 	// @ 
			jTableMarker = new JTable(TableModel); // @
			jTableMarker.addKeyListener(new KeyAdapter() {
				@Override
				public void keyReleased(KeyEvent arg0) {
					//setDiff();
				}
			});
			jTableMarker.setAutoResizeMode(JTable.AUTO_RESIZE_SUBSEQUENT_COLUMNS);
		//	jTableDisplayProperty.setDefaultEditor(Object.class, null);
			jTableMarker.setColumnSelectionAllowed(true);
			jTableMarker.setRowSelectionAllowed(true);
			jTableMarker.setSelectionMode(ListSelectionModel.MULTIPLE_INTERVAL_SELECTION);
			
			{
			JumpButtonEditor editor = new JumpButtonEditor(jTableMarker);	//@
			
			JumpButtonRenderer renderer = new JumpButtonRenderer();			// @
			int col = getColumnFromName("Go");
			TableColumn column0 = jTableMarker.getColumnModel().getColumn(col);
	        column0.setCellEditor(editor);
	        column0.setCellRenderer(renderer);
	        
	        EditEndNotifyEditor editor2 = new EditEndNotifyEditor(new JTextField());
	        col = getColumnFromName("Index");
	        column0 = jTableMarker.getColumnModel().getColumn(col);
	        column0.setCellEditor(editor2);
	        editor2 = new EditEndNotifyEditor(new JTextField());
	        col = getColumnFromName("Time");
	        column0 = jTableMarker.getColumnModel().getColumn(col);
	        column0.setCellEditor(editor2);
			}
	        
		//	jTableMarker.setDefaultRenderer(Double.class, new DoubleRenderer());
			jTableMarker.addPropertyChangeListener(new java.beans.PropertyChangeListener() {
				public void propertyChange(java.beans.PropertyChangeEvent e) {
					if ((e.getPropertyName().equals("model"))) {
						System.out.println("propertyChange(model)");  
					}
				}
			});
			jTableMarker.addMouseListener(new java.awt.event.MouseAdapter() {
				public void mouseClicked(java.awt.event.MouseEvent e) {
				}
			});
			jTableMarker.setAutoCreateRowSorter(true);		
			TableColumnModel mdl = jTableMarker.getColumnModel();
			int col = getColumnFromName("Index");
			TableColumn dl = mdl.getColumn(col);
			dl.setMaxWidth(40);
			dl.setMinWidth(40);
			col = getColumnFromName("Time");
			dl = mdl.getColumn(col);
			dl.setMinWidth(150);
			col = getColumnFromName("Go");
			dl = mdl.getColumn(col);
			dl.setMaxWidth(50);
			dl.setMinWidth(50);
		}
		return jTableMarker;
	}

	/**
	 *  マーカーを増やす
	 * @return
	 */
	
	private JButton getBtnAdd() {
		if (btnAdd == null) {
			btnAdd = new JButton("Add Marker Special");
			btnAdd.setPreferredSize(new Dimension(180, 25));
			btnAdd.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent arg0) {
					
					int rindex = findMarkerViewIndex(0);
					int totalnum = jTableMarker.getRowCount();
					if(rindex<0 || totalnum != 1){
						JOptionPane.showMessageDialog(null
								,"Set Olny Reference marker([0]).\n To put a Reference marker, use Ctrl+Shift Left Click on the Time-series View "
								);
						return;
					}
					//int markerNum = 10; // number of adding marker 
					//int markerStep = 60; // sec;
					DialogMarkerAddSpecialParameter dlg = new DialogMarkerAddSpecialParameter(Owner);
					dlg.Interval = AddSpecialMarkerStep;
					dlg.Number = AddSpecialMarkerNum;
					dlg.SetValue();
					
					dlg.setLocation(getLocationOnScreen());
					dlg.setVisible(true);
					if(!dlg.OK) return;
					AddSpecialMarkerStep = dlg.Interval;
					AddSpecialMarkerNum = dlg.Number;
					
					int tmidx = getColumnFromName("Time");
					//int dfidx = getColumnFromName("From marker [0]");
					wintime wt = getWinTimeFromTable(rindex,tmidx);
					for(int i=0;i<AddSpecialMarkerNum;i++){
						wt.inc_sec(AddSpecialMarkerStep);
						addTime(wt ,i+1);
					}
					Parent.repaintAll();
					
				}
			});
		}
		return btnAdd;
	}
	
}  //  @jve:decl-index=0:visual-constraint="10,10"
